﻿using Newtonsoft.Json;
using StackExchange.Redis;

namespace Colorful.Caching;

/// <summary>
///  StackExchangeRedis缓存
/// </summary>
public class StackExchangeRedisCache : IRedisCache
{
    private readonly IDatabase _db;

    public StackExchangeRedisCache(IDatabase db)
    {
        _db = db;
    }

    /// <summary>
    ///  改变数据库
    /// </summary>
    /// <param name="dbValue">数据值</param>
    /// <returns></returns>
    public IRedisCache ChangeDb(int dbValue)
    {
        _db.Multiplexer.GetDatabase(dbValue);

        return this;
    }

    /// <summary>
    ///  设置缓存
    /// </summary>
    /// <typeparam name="T">泛型</typeparam>
    /// <param name="key">redis键</param>
    /// <param name="value">redis值</param>
    /// <param name="expireSeconds">过期时间，默认为不过期</param>
    public async Task<bool> SetAsync<T>(string key, T value, int expireSeconds = -1)
    {
        if (value == null)
            throw new ArgumentNullException(nameof(value));

        if (string.IsNullOrWhiteSpace(key))
            throw new ArgumentException(nameof(key));

        var redisValue = JsonConvert.SerializeObject(value);

        if (expireSeconds != -1)
        {
            return await _db.StringSetAsync(key, redisValue, TimeSpan.FromSeconds(expireSeconds));
        }

        return await _db.StringSetAsync(key, redisValue);
    }

    /// <summary>
    ///  设置缓存
    /// </summary>
    /// <typeparam name="T">泛型</typeparam>
    /// <param name="key">redis键</param>
    /// <param name="value">redis值</param>
    /// <param name="expireSeconds">过期时间，默认为不过期</param>
    public bool Set<T>(string key, T value, int expireSeconds = -1)
    {
        if (value == null)
            throw new ArgumentNullException(nameof(value));

        if (string.IsNullOrWhiteSpace(key))
            throw new ArgumentException(nameof(key));

        var redisValue = JsonConvert.SerializeObject(value);

        if (expireSeconds != -1)
        {
            return _db.StringSet(key, redisValue, TimeSpan.FromSeconds(expireSeconds));
        }

        return _db.StringSet(key, redisValue);
    }

    /// <summary>
    ///  从缓存中获取泛型的方法
    /// </summary>
    /// <typeparam name="T">泛型</typeparam>
    /// <param name="key">键</param>
    /// <returns>T?</returns>
    public async Task<T?> GetAsync<T>(string key)
    {
        if (string.IsNullOrWhiteSpace(key))
            throw new ArgumentException(nameof(key));

        var redisValue = await _db.StringGetAsync(key);

        return string.IsNullOrWhiteSpace(redisValue)
            ? default
            : JsonConvert.DeserializeObject<T>(redisValue);
    }

    /// <summary>
    ///  从缓存中获取泛型的方法
    /// </summary>
    /// <typeparam name="T">泛型</typeparam>
    /// <param name="key">redis键</param>
    /// <returns>T?</returns>
    public T? Get<T>(string key)
    {
        if (string.IsNullOrWhiteSpace(key))
            throw new ArgumentException(nameof(key));

        var redisValue = _db.StringGet(key);

        return string.IsNullOrWhiteSpace(redisValue)
            ? default
            : JsonConvert.DeserializeObject<T>(redisValue);
    }

    /// <summary>
    ///  删除缓存
    /// </summary>
    /// <param name="key">redis键</param>
    /// <returns></returns>
    public bool Delete(string key)
    {
        return _db.KeyDelete(key);
    }

    /// <summary>
    ///  删除缓存
    /// </summary>
    /// <param name="key">redis键</param>
    /// <returns></returns>
    public async Task<bool> DeleteAsync(string key)
    {
        return await _db.KeyDeleteAsync(key);
    }
}